package com.xjk.encryp;

import java.security.GeneralSecurityException;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * AES加密工具
 * 
 * @author shuanglin.luo
 *
 */
public class AesEncrypt{

    private static final String AES_ALG = "AES";

    /**
     * AES算法
     */
    private static final String AES_CBC_PCK_ALG = "AES/CBC/PKCS5Padding";

    /**
     * 向量
     */
    private static final byte[] AES_IV = initIv(AES_CBC_PCK_ALG);

    /**
     * AES加密
     * 
     * @param content
     * @param aesKey
     * @param charset
     * @return
     * @throws Exception
     */
    public static String aesEncrypt(String content,byte[] aesKey,String charset) throws Exception{
        Cipher cipher = Cipher.getInstance(AES_CBC_PCK_ALG);
        IvParameterSpec iv = new IvParameterSpec(AES_IV);
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(Base64.encodeBase64(aesKey), AES_ALG), iv);
        byte[] encryptBytes = cipher.doFinal(content.getBytes(charset));
        return new String(Base64.encodeBase64(encryptBytes));
    }

    /**
     * AES解密
     * 
     * @param content
     * @param aesKey
     * @param charset
     * @return
     * @throws Exception
     */
    public static String aesDecrypt(String content,byte[] aesKey,String charset) throws Exception{
        Cipher cipher = Cipher.getInstance(AES_CBC_PCK_ALG);
        IvParameterSpec iv = new IvParameterSpec(initIv(AES_CBC_PCK_ALG));
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(Base64.encodeBase64(aesKey), AES_ALG), iv);
        byte[] cleanBytes = cipher.doFinal(Base64.decodeBase64(content.getBytes()));
        return new String(cleanBytes, charset);

    }

    /**
     * 初始向量的方法, 全部为0. 这里的写法适合于其它算法,针对AES算法的话,IV值一定是128位的(16字节).
     *
     * @param fullAlg
     * @return
     * @throws GeneralSecurityException
     */
    private static byte[] initIv(String fullAlg){

        try{
            Cipher cipher = Cipher.getInstance(fullAlg);
            int blockSize = cipher.getBlockSize();
            byte[] iv = new byte[blockSize];
            for (int i = 0; i < blockSize; ++i){
                iv[i] = 0;
            }
            return iv;
        }catch (Exception e){

            int blockSize = 16;
            byte[] iv = new byte[blockSize];
            for (int i = 0; i < blockSize; ++i){
                iv[i] = 0;
            }
            return iv;
        }
    }
}
